#include<iostream>
#include<pthread.h>
#include<vector>
#include<string>
#include<unistd.h>

#define NUMS 5 //实现5个线程，同时抢1000张票的代码

using namespace std;

int tickets=1000;

pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;//宏初始化锁，就无需对锁init和destroy

//创建一个封装了锁的功能的类，用类对象的生命周期充当加锁解锁的条件
//实现多线程的加锁，前提就是多线程使用同一把锁，即锁不能放在各线程的栈结构中，而应该定义在全局空间上
class MutexGuard
{
public:
    MutexGuard(pthread_mutex_t* mutex):_mutex(mutex)
    {   
        pthread_mutex_lock(_mutex);//加锁
    }
    ~MutexGuard()
    {
        pthread_mutex_unlock(_mutex);//销毁前，先解锁
    }
private:
    pthread_mutex_t* _mutex;
};

//创建一个结构体，存放main函数想要传递给args的参数
class ThreadData
{
public:
    ThreadData(int number)
    {
        _pthreadname="thread_" + to_string(number);
    }
    const char* Getname()
    {
        return _pthreadname.c_str();
    }
private:
    string _pthreadname;//线程名
};

void* Grab_tickets(void* args)
{
    ThreadData* td=static_cast<ThreadData*>(args);
    const char* name = td->Getname();
    while(true)
    {
        MutexGuard mutex_guard(&lock);//用mutex_guard的生命周期来加锁、解锁
        if(tickets>0)
        {
            usleep(1000);
            printf("who=%s,get a ticket : %d\n",name,tickets);
            tickets--;
        }
        else 
        {
            break;
        }
    }

    return nullptr;
}

int main()
{
    //创建多线程
    vector<pthread_t> tids;//把创建出来的多线程放在一个顺序表里
    vector<ThreadData*> thread_data;
    for(int i=0;i<NUMS;i++)
    {
        pthread_t tid;
        ThreadData* td=new ThreadData(i);
        thread_data.push_back(td);

        pthread_create(&tid,nullptr,Grab_tickets,thread_data[i]);

        tids.push_back(tid);
    }

    //对线程等待回收
    for(int i=0;i<NUMS;i++)
    {
        pthread_join(tids[i],nullptr);
        delete thread_data[i];
    }
    cout<<"main释放线程完毕"<<endl;

    //pthread_mutex_destroy(&mutex);//销毁指定的锁
    return 0;
}